 <!-- dat.gui threejs 官方调试工具
  相机切换
  -->
  <template>
    <div ref="Cavans"></div>
</template>
<script setup>
import { createHelper, resizeHandler, THREE, createGui } from '@/utils/threejs'
// import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { OrbitControls } from 'three/addons/controls/OrbitControls'
import Stats from 'three/examples/jsm/libs/stats.module';

const Cavans = ref(null)
const guiConfig = {
    wireframe: false,
    // 相机切换
    switchCamera: () => {
        if(camera.type === "PerspectiveCamera"){
            camera = orthoCamera
            controls.enabled = false
        } else {
            camera = watcherCamera
            controls.enabled = true
        }
    }
}
let camera
// 创建一个场景
const scene = new THREE.Scene()
// 初始化调试
const gui = createGui()
// 创建一个正交相机  OrthographicCamera 正交投影相机 六个参数 近截面（near） 远截面（far）
// orthographiccamera( left : Number, right : Number, top : Number, bottom : Number, near : Number, far : Number )
// left — 摄像机视锥体左侧面。
// right — 摄像机视锥体右侧面。
// top — 摄像机视锥体上侧面。
// bottom — 摄像机视锥体下侧面。
// near — 摄像机视锥体近端面。
// far — 摄像机视锥体远端面。
const size = 4
const orthoCamera = new THREE.OrthographicCamera(-size, size, size, -size, 0.001, 10)
orthoCamera.lookAt(scene.position)
scene.add(orthoCamera)
// 相机位置
orthoCamera.position.set(0, 0, 5);// 相机默认坐标是(0,0,0)
// 添加第二个相机   PerspectiveCamera 透视投影相机 四个参数 视野角度（FOV）长宽比（aspect ratio）近截面（near） 远截面（far）
const watcherCamera = new THREE.PerspectiveCamera( 75, document.body.clientWidth / document.body.clientHeight, 0.1, 100 )
watcherCamera.position.set(1, 0.5, 10)
watcherCamera.lookAt(scene.position)
scene.add(watcherCamera)
camera = watcherCamera
// 渲染器
const renderer = new THREE.WebGLRenderer({
    antialias: true, // 抗锯齿
})
// 创建辅助
createHelper(scene)
// 优化 设置像素比
renderer.setPixelRatio(window.devicePixelRatio || 1)
// 渲染器的尺寸
renderer.setSize(document.body.clientWidth, document.body.clientHeight)
// geometry 几何体 创建一个立方体 BoxGeometry
const geometry = new THREE.BoxGeometry( 1, 1, 1 )
// 添加全局光照 AmbientLight ambientlight( color : Integer, intensity : Float ) 环境光会均匀的照亮场景中的所有物体。
// color - (参数可选）颜色的rgb数值。缺省值为 0xffffff。 十六进制
// intensity - (参数可选)光照的强度。缺省值为 1。
const light = new THREE.AmbientLight(0xffffff, 0.5)
// 添加方向光 平行光（directionallight） 平行光是沿着特定方向发射的光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5)
scene.add(light, directionalLight)
// 颜色
const color = new THREE.Color(Math.random(), Math.random(), Math.random())
const faces = []
for(let i = 0; i < geometry.groups.length; i++){
    const material = new THREE.MeshBasicMaterial({
        color: new THREE.Color(Math.random(), Math.random(), Math.random()),
    })
    faces.push(material)
}
// Mesh 网格  网格包含一个几何体 geometry 以及作用在此几何体上的材质 material
const cube = new THREE.Mesh( geometry, faces );
cube.position.x = -4
// 矩形平面
const planeGeometry = new THREE.PlaneGeometry(1, 1)
// 圆锥体
const coneGeometry = new THREE.ConeGeometry( 0.5, 1, 32 );
// 圆柱体
const cylinderGeometry = new THREE.CylinderGeometry( 0.5, 0.5, 1, 32 );
const meshBasicMaterial =  new THREE.MeshBasicMaterial({
        color: new THREE.Color(Math.random(), Math.random(), Math.random()),
        side: THREE.DoubleSide // 性能考虑，默认只渲染一面，需手动开启两面渲染
    })
const plane = new THREE.Mesh(planeGeometry, meshBasicMaterial)
const cone = new THREE.Mesh(coneGeometry, meshBasicMaterial)
const cylinder = new THREE.Mesh(cylinderGeometry, meshBasicMaterial)
plane.position.x = -2
cone.position.x = 0
cylinder.position.x = 2
// 调用 scene.add()，物体将会被添加到 (0,0,0) 坐标
scene.add(cube, plane, cone, cylinder)
const controls = new OrbitControls(camera,renderer.domElement) 
// 将其设置为true以启用阻尼（惯性），这将给控制器带来重量感。默认值为false。 请注意，如果该值被启用，你将必须在你的动画循环里调用update()
controls.enableDamping = true 
// 当.enableDamping设置为true的时候，阻尼惯性有多大。 Default is 0.05. 请注意，要使得这一值生效，你必须在你的动画循环里调用 update()
controls.dampingFactor = 0.03
// 添加性能监控器
const stats = new Stats()
stats.setMode(0)
const animate = () => {
    // 浏览器API
	requestAnimationFrame( animate );
    controls.update() // 更新轨道控制器  
    stats.update() // 更新监控帧数
	renderer.render( scene, camera );
}
animate();
// 自适应
resizeHandler(renderer, camera)
// gui 调试
// gui.add() 
// 参数 target: object, propName: never, min?: number, max?: number, step?: number
gui.add(camera.position,'x',0.1,10,0.1).name('positionX')
gui.add(cube.rotation,'x',1,10,1).name('rotationX')
// 参数为自定义对象
gui.add(guiConfig,'wireframe').onChange((val)=>{
    // wireframe 是否启用线框模式，默认为 false
    cube.material.forEach((item)=>item.wireframe=val)
    plane.material.wireframe=val
    cone.material.wireframe=val
    cylinder.material.wireframe=val
})
// 参数为函数
gui.add(guiConfig,'switchCamera')
onMounted(()=>{
    // 挂载
    Cavans.value.appendChild(renderer.domElement)
    Cavans.value.appendChild(stats.domElement)
})
</script>
